﻿using System;
using System.Collections.Generic;
using System.Text;
using Shapes.Geometry;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Shapes.Misc.Appearance
{
    /// <summary>
    /// Indicates what should happen if the position to fill is outside the fill's bounds
    /// </summary>
    public enum FillOption
    {
        /// <summary>displays everything outside of the bounds transparent</summary>
        Transparent = 0,
        /// <summary>the fill will be repeated outside of the bounds</summary>
        Repeat = 1,
    }

    /// <summary>
    /// Base class for Fill objects.
    /// Any Fill object can be passed to the TextureGenerator to give your shapes a better look
    /// </summary>
    public abstract class Fill
    {
        /// <summary>
        /// The transformation of the fill (like texture-coordinates)
        /// </summary>
        public Transformation2D Transform { get; set; }
        /// <summary>
        /// The option which indicates the behaviour outside of the Transforms bounds
        /// </summary>
        public FillOption FillOption { get; set; }

        /// <summary>
        /// Base Constructor for Fill
        /// </summary>
        /// <param name="width">the width of the bounds</param>
        /// <param name="height">the height of the bounds</param>
        protected Fill(float width, float height)
        {
            FillOption = FillOption.Repeat;
            Transform = new Transformation2D(Vector2.Zero, width, height);
        }

        /// <summary>
        /// Gets the color at the given point
        /// </summary>
        /// <param name="position">the position in the local space of the holding shape</param>
        /// <returns>the color at the given point</returns>
        public Color GetColorAt(Vector2 position)
        {
            Transform.TransformGlobalToLocal(ref position);

            if (!Transform.Contains(ref position))
            {
                switch (FillOption)
                {
                    case FillOption.Transparent:
#if XNA4
                        return Color.Transparent;
#else
                        return Color.TransparentBlack;
#endif

                    case FillOption.Repeat:
                        
                        while (position.X < 0)
                            position.X += 10 * Transform._Width;
                        
                        while (position.Y < 0)
                            position.Y += 10 * Transform._Height;

                        position.X %= Transform._Width;
                        position.Y %= Transform._Height;

                        break;
                }
            }

            return GetColorAt(ref position);
        }
        /// <summary>
        /// Mehtod to evaluate the color at the given position
        /// </summary>
        /// <param name="position">the position in local space of the fill</param>
        /// <returns>the color at the given point</returns>
        protected abstract Color GetColorAt(ref Vector2 position);
    }
}
